package com.jhd.jiangxi;


import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jhd.jiangxi.downloadmanager.Utils.DeviceUtils;
import com.jhd.jiangxi.service.SendErrorService;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.fastjson.FastJsonConverterFactory;

public class CrashHandler implements Thread.UncaughtExceptionHandler {
    private static final String TAG = "CrashHandler";
    private static final boolean DEBUG = true;
    private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/CrashTest/log/";
    private static final String FILE_NAME = "crash";
    private static final String FILE_NAME_SUFFIX = ".trace";

    private static CrashHandler sInstance = new CrashHandler();
    private Thread.UncaughtExceptionHandler mDefaultCrashHandler;
    private Context mContext;

    public CrashHandler() {
    }

    public static CrashHandler getsInstance() {
        return sInstance;
    }

    public void init(Context context) {
        mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
        mContext = context.getApplicationContext();
    }

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        try {
            //导出信息到SD卡中
//            dumpExceptionToSDCard(throwable);
            //上传异常信息到服务器
            uploadExceptionToService(throwable);
        } catch (Exception e) {
            e.printStackTrace();
        }
        throwable.printStackTrace();

        //如果系统提供了默认的异常处理,则交给系统去结束程序,否则自己结束自己
        if (mDefaultCrashHandler != null) {
            mDefaultCrashHandler.uncaughtException(thread, throwable);
        } else {
            android.os.Process.killProcess(android.os.Process.myPid());
        }
    }

    //导出到SDCard
    private void dumpExceptionToSDCard(Throwable ex) throws IOException {
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            if (DEBUG) {
                Log.e("TAG", "dumpExceptionToSDCard: SdCard unmounted,skip dump exception");
                return;
            }
        }

        File dir = new File(PATH);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        long current = System.currentTimeMillis();
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current));
        File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);

        try {
            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            pw.println(time);
            dumpPhoneInfo(pw);
            pw.println();
            ex.printStackTrace(pw);
            pw.close();

        } catch (Exception e) {
            Log.e("TAG", "dumpExceptionToSDCard: dump crash info failed");
        }

    }

    private void dumpPhoneInfo(PrintWriter pw) throws PackageManager.NameNotFoundException {
        PackageManager pm = mContext.getPackageManager();
        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
        pw.print("App Version:");
        pw.print(pi.versionName);
        pw.print("-");
        pw.println(pi.versionCode);

        //Android 版本号
        pw.print("OS Version:");
        pw.print(Build.VERSION.RELEASE);
        pw.print("-");
        pw.println(Build.VERSION.SDK_INT);

        //手机制造商
        pw.print("Vendor:");
        pw.println(Build.MANUFACTURER);

        //手机型号
        pw.print("Model:");
        pw.println(Build.MODEL);

        //CPU
        pw.print("CPU ABI:");
        pw.println(Build.CPU_ABI);


    }

    private void uploadExceptionToService(Throwable ex) {
        //TODO 上传服务器操作
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            PrintWriter pw = new PrintWriter(os);
            ex.printStackTrace(pw);
            pw.flush();
            String trace = new String(os.toByteArray(), 0, os.toByteArray().length);
            ErrInfo ei = new ErrInfo();
            ei.setVersion(String.valueOf(DeviceUtils.getVersionCode(mContext)));
            ei.setTrace(trace);
            ei.setMsg(ex.getMessage());
            ei.setUser(((ScanApplication) mContext).getUserName());
            ei.setDept(((ScanApplication) mContext).getDeptName());
            ei.setType("jiangxi");
            sendError(ei);
        } catch (Exception e) {
            Log.e("TAG", "uploadExceptionToService: dump crash info failed");
        }

    }

    public class ErrInfo {
        private String version;
        private String user;
        private String dept;
        private String msg;
        private String trace;
        private String type="jiangxi";

        public String getVersion() {
            return version;
        }

        public void setVersion(String version) {
            this.version = version;
        }

        public String getUser() {
            return user;
        }

        public void setUser(String user) {
            this.user = user;
        }

        public String getDept() {
            return dept;
        }

        public void setDept(String dept) {
            this.dept = dept;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public String getTrace() {
            return trace;
        }

        public void setTrace(String trace) {
            this.trace = trace;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }
    }

    protected void sendError(ErrInfo ei) {

        Retrofit retrofit = new Retrofit.Builder().baseUrl(UtilHelper.baseUrls.ERR_TRACE).addConverterFactory(FastJsonConverterFactory.create()).build();//UtilHelper.retrofit(application,UtilHelper.baseUrls.EMIAO(application.getBackSystem()));
        SendErrorService se = retrofit.create(SendErrorService.class);
//        String token = ((ScanApplication)mContext).getAccessToken();
        RequestBody requestBody = RequestBody.create(MediaType.parse("Content-Type, application/json"),
                JSON.toJSONString(ei));

        Call<ResponseBody> jsonForResultCall = se.sendError(requestBody);
        jsonForResultCall.enqueue(new SendErrorCallback());
    }

    private class SendErrorCallback implements Callback<ResponseBody> {

        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            try {
                JSONObject json = JSONObject.parseObject(response.body().string());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable throwable) {
            String msg = throwable.getMessage();
        }
    }

}
